package com.xiyuan.smartutils.api;

import com.xiyuan.smartutils.Randoms;
import com.xiyuan.smartutils.StrUtils;
import com.xiyuan.smartutils.api.annotation.ApiField;
import com.xiyuan.smartutils.constants.CodeConstants;

import java.io.Serializable;

/**
 * 公共响应结果
 *
 * @author xiyuan-lgz 2023-09-16 @version v1.0.0 新建与整理
 */
@SuppressWarnings({"all"})
public class ApiResult<T> implements Serializable, CodeConstants {
    private static final long serialVersionUID = 1L;
    
    /**
     * 默认失败
     */
    private static String SUCC = "0";
    private static String FAIL = "99999";
    
    /**
     * 设置全局 成功，和 失败 公共错误吗
     *
     * @param succCode 成功错误码
     * @param failCode    公共失败错误码
     */
    public static void setDefault(Number succCode, Number failCode) {
        SUCC = String.valueOf(succCode == null ? SUCC : succCode.longValue());
        FAIL = String.valueOf(failCode == null ? FAIL : failCode.longValue());
    }
    
    /**
     * 设置全局 成功，和 失败 公共错误吗
     *
     * @param successCode 成功错误码
     * @param failCode    公共失败错误码
     */
    public static void setDefault(String successCode, String failCode) {
        SUCC = StrUtils.trimToNull(successCode);
        FAIL = String.valueOf(failCode);
    }
    
    /**
     * 消息ID
     */
    private String msgId = Randoms.random(16);
    
    /**
     * 数据内容
     */
    private T data;
    
    /**
     * 其他数据内容
     */
    private Object other;
    
    /**
     * 请求消息内容
     */
    private String msg = "失败";
    
    
    /**
     * 请求状态吗
     */
    private String code = FAIL;// 通用失败
    
    
    /**
     * 子状态码
     */
    private String subCode;
    
    /**
     * 子状态吗描述
     */
    private String subMsg;
    
    public ApiResult() {}
    
    public ApiResult(String code, T data, String msg) {
        this.code = code;
        this.data = data;
        this.msg = msg;
    }
    
    public ApiResult(int code, T data, String msg) {
        this(String.valueOf(code), data, msg);
    }
    
    
    public static ApiResult ok(Object data, String msg, Object other) {
        return new ApiResult(SUCC, data, msg).setOther(other);
    }
    
    public static ApiResult ok(String msg, Object data) {
        return ok(data, msg, null);
    }
    
    public static ApiResult ok() {
        return ok(null, null);
    }
    
    public static ApiResult ok(String msg) {
        return ok(null, msg);
    }
    
    public static ApiResult ok(Object data) {
        return ok(data, null, null);
    }
    
    public static ApiResult fail(String code, String msg, Object data, String subCode, String subMsg) {
        return SUCC.equals(String.valueOf(code))
               ? ok(msg, data)
               : new ApiResult(code, data, msg).setSubCode(subCode).setSubMsg(subMsg);
    }
    
    public static ApiResult fail(int code, String msg, Object data, String subCode, String subMsg) {
        return SUCC.equals(String.valueOf(code))
               ? ok(msg, data)
               : new ApiResult(code, data, msg).setSubCode(subCode).setSubMsg(subMsg);
    }
    
    public static ApiResult fail(int code, String msg, Object data) {
        return fail(code, msg, data, null, null);
    }
    
    public static ApiResult fail(int code, String msg) {
        return fail(code, msg, null, null, null);
    }
    public static ApiResult fail(String code, String msg) {
        return fail(code, msg, null, null, null);
    }
    public static ApiResult fail(int code) {
        return fail(code, null, null, null, null);
    }
    
    public static ApiResult fail(String msg) {
        return fail(FAIL, msg, null, null, null);
    }
    public static ApiResult fail( Object data, String msg) {
        return fail(FAIL, msg, data, null, null);
    }
    public static ApiResult fail(int code, Object data) {
        return fail(code, null, data, null, null);
    }
    public static ApiResult fail(String code, Object data) {
        return fail(code, null, data, null, null);
    }
    public static ApiResult fail() {
        return new ApiResult(FAIL, null, null);
    }
    
    
    /*******************************************************************/
    // 以下是 对象私有提供的方法
    
    /*******************************************************************/
    
    /**
     * 是成功
     *
     * @return true | false
     */
    public boolean isOK() {
        return SUCC.equals(this.code);
    }
    
    /**
     * 获取消息ID
     *
     * @return 消息ID
     */
    public String getMsgId() {
        return msgId;
    }
    
    /**
     * 设置消息ID
     *
     * @param msgId 消息ID
     * @return 返回当前 对象
     */
    public ApiResult<T> setMsgId(String msgId) {
        this.msgId = msgId;
        return this;
    }
    
    /**
     * 设置主体内容
     *
     * @param data 主体内容
     * @return 当我对象
     */
    public ApiResult<T> setData(T data) {
        this.data = data;
        return this;
    }
    
    /**
     * 获取消息 内容
     *
     * @param msg 消息内容
     * @return 当前对象
     */
    
    public ApiResult<T> setMsg(String msg) {
        this.msg = msg;
        return this;
    }
    
    /**
     * 设置响应状态吗
     *
     * @param code 状态码
     * @return 当前对象
     */
    public ApiResult<T> setCode(String code) {
        this.code = code;
        return this;
    }
    
    
    /**
     * 获取状态码
     *
     * @return code
     */
    public String getCode() {
        return code;
    }
    
    public String getSubCode() {
        return subCode;
    }
    
    public ApiResult<T> setSubCode(String subCode) {
        this.subCode = subCode;
        return this;
    }
    
    public String getMsg() {
        return msg;
    }
    
    public String getSubMsg() {
        return subMsg;
    }
    
    public ApiResult<T> setSubMsg(String subMsg) {
        this.subMsg = subMsg;
        return this;
    }
    
    public T getData() {
        return data;
    }
    
    public <O> O getOther() {
        return (O) other;
    }
    
    public ApiResult<T> setOther(Object other) {
        this.other = other;
        return this;
    }
}
